package io.plus.interactive;

import drds.common.Clock;
import io.plus.client.ClientConfiguration;
import io.plus.interactive.collections.*;
import io.plus.interactive.task.CloseTask;
import io.plus.interactive.user_interface.AioHandler;
import io.plus.interactive.user_interface.AioListener;
import io.plus.interactive.user_interface.GroupListener;
import io.plus.interactive.user_interface.Packet;
import io.plus.server.ServerConfiguration;
import io.plus.utils.Threads;
import io.plus.utils.lock.ReadWriteLockMap;
import io.plus.utils.lock.ReadWriteLockSet;
import io.plus.utils.prop.ReadWriteLocPropertiesk;
import io.plus.utils.thread.lock_capable_task.LockCapableRunnableThreadPoolExecutor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Data
public abstract class Configuration extends ReadWriteLocPropertiesk {
    /**
     * 默认的接收数据的buffer size
     */
    public static final int READ_BUFFER_SIZE = Integer.getInteger("tio.default.read.buffer.size", 20480);
    /**
     * 本jvm中所有的ServerTioConfig对象
     */
    public static final Set<ServerConfiguration> ALL_SERVER_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的ClientTioConfig对象
     */
    public static final Set<ClientConfiguration> ALL_CLIENT_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的TioConfig对象
     */
    public static final Set<Configuration> ALL_GROUPCONTEXTS = new HashSet<>();
    private final static AtomicInteger ID_ATOMIC = new AtomicInteger();
    //static Logger log = LoggerFactory.getLogger(Configuration.class);
    public boolean isShortConnection = false;
    public boolean debug = false;

    public PacketConverter packetConverter = null;
    /**
     * 启动时间
     */
    public long startTime = Clock.currentTimeMillis;
    /**
     * 是否用队列发送
     */
    public boolean useQueueSend = true;
    /**
     * 是否用队列解码（系统初始化时确定该值，中途不要变更此值，否则在切换的时候可能导致消息丢失）
     */
    public boolean useQueueDecode = false;
    /**
     * 心跳超时时间(单位: 毫秒)，如果用户不希望框架层面做心跳相关工作，请把此值设为0或负数
     */
    public long heartbeatTimeout = 1000 * 120;
    public PacketHandlerMode packetHandlerMode = PacketHandlerMode.SINGLE_THREAD;                                    //.queue;
    public LockCapableRunnableThreadPoolExecutor tioExecutor = null;
    public CloseTask closeRunnable;
    public ThreadPoolExecutor groupExecutor = null;
    public ClientNodes clientNodes = new ClientNodes();
    public ReadWriteLockSet<AsynchronousSocketChannelContext> connections = new ReadWriteLockSet<AsynchronousSocketChannelContext>(new HashSet<AsynchronousSocketChannelContext>());
    public Groups groups = new Groups();
    public Users users = new Users();
    public Tokens tokens = new Tokens();
    public Ids ids = new Ids();
    public BusinessIds businessIds = new BusinessIds();
    public Ips ips = new Ips();
    //public IpStates ipStates = null;
    /**
     * ip黑名单
     */
    public IpBlackList ipBlacklist = null;
    public ReadWriteLockMap<Integer, Packet> waitingResps = new ReadWriteLockMap<Integer, Packet>(new HashMap<Integer, Packet>());
    protected String id;
    /**
     * 解码异常多少次就把ip拉黑
     */
    protected int maxDecodeErrorCountForIp = 10;
    protected String name = "未命名";
    private ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
    /**
     * 接收数据的buffer size
     */
    private int readBufferSize = READ_BUFFER_SIZE;
    private GroupListener groupListener = null;
    private boolean isStopped = false;

    /**
     * 如果此值不为null，就表示要集群
     */
    public Configuration() {
        this(null, null);
    }

    public Configuration(LockCapableRunnableThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) {
        super();
        ALL_GROUPCONTEXTS.add(this);
        if (this instanceof ServerConfiguration) {
            ALL_SERVER_GROUPCONTEXTS.add((ServerConfiguration) this);
        } else {
            ALL_CLIENT_GROUPCONTEXTS.add((ClientConfiguration) this);
        }

        if (ALL_GROUPCONTEXTS.size() > 20) {
            log.warn("已经产生{}个TioConfig对象，t-io作者怀疑你在误用t-io", ALL_GROUPCONTEXTS.size());
        }
        this.id = ID_ATOMIC.incrementAndGet() + "";

        //this.ipStates = new IpStates(this, null);

        this.tioExecutor = tioExecutor;
        if (this.tioExecutor == null) {
            this.tioExecutor = Threads.getLockCapableRunnableThreadPoolExecutor();
        }

        this.groupExecutor = groupExecutor;
        if (this.groupExecutor == null) {
            this.groupExecutor = Threads.getThreadPoolExecutor();
        }

        closeRunnable = new CloseTask(this.tioExecutor);
    }


    /**
     * 获取AioHandler对象
     */
    public abstract AioHandler getAioHandler();

    /**
     * 获取AioListener对象
     */
    public abstract AioListener getAioListener();

    /**
     * 是否用队列解码（系统初始化时确定该值，中途不要变更此值，否则在切换的时候可能导致消息丢失
     */
    public void setUseQueueDecode(boolean useQueueDecode) {
        this.useQueueDecode = useQueueDecode;
    }

    /**
     * 是否用队列发送，可以随时切换
     */
    public void setUseQueueSend(boolean useQueueSend) {
        this.useQueueSend = useQueueSend;
    }

    /**
     * 是服务器端还是客户端
     */
    public abstract boolean isServer();

}
